{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# DC Extrapolation for Time Domain " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When converting S-parameters to time domain the frequency points should be equally spaced and start from 0 Hz. Usually VNA doesn't measure down to DC and DC point should be added afterwards.\n", "\n", "When a DC point measurement is added it might be the case that frequency point spacing between the DC and the first measured point is not equal to the spacing between the other measured points. Since time domain conversion relies on Fourier transform that assumes regularly spaced points, the measurements should also be resampled to be equally spaced." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "\n", "import skrf as rf\n", "from skrf.media import Coaxial\n", "from skrf.plotting import stylely\n", "\n", "stylely()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "freq = rf.Frequency(0.11, 110, 401, 'GHz')\n", "coax1mm = Coaxial(freq, Dint=0.44e-3, Dout=1.0e-3, sigma=1e20, z0_port = 50)\n", "\n", "X = coax1mm.line(10, unit='mm', z0=50, name='X')\n", "Y = coax1mm.line(80, unit='mm', z0=75, name='Y')\n", "dut = X**Y**X\n", "dut.name = 'Original'\n", "\n", "dut_dc = dut.extrapolate_to_dc(dc_sparam=[[0,1],[1,0]])\n", "dut_dc.name = 'Extrapolated'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "plt.title('Step response')\n", "dut.plot_z_time_step(0, 0)\n", "dut_dc.plot_z_time_step(0, 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interpolation method comparison" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Frequency points for measurements to be interpolated\n", "# Frequencies from 0 to 1 GHz are missing\n", "freq = rf.Frequency(1, 110, 601, 'GHz')\n", "# Frequency for ideal\n", "freq2 = rf.Frequency(0, 110, 602, 'GHz')\n", "coax1mm = Coaxial(freq, z0_port=50, Dint=0.44e-3, Dout=1.0e-3, sigma=1e20)\n", "coax1mm2 = Coaxial(freq2, z0_port=50, Dint=0.44e-3, Dout=1.0e-3, sigma=1e20)\n", "\n", "# Generate the DUT\n", "X = coax1mm.line(10, 'mm', z0=50, name='X')\n", "Y = coax1mm.line(80, 'mm', z0=75, name='Y')\n", "dut = X**Y**X\n", "\n", "# DUT with full frequencies for comparison\n", "X2 = coax1mm2.line(10, 'mm', z0=50, name='X')\n", "Y2 = coax1mm2.line(80, 'mm', z0=75, name='Y')\n", "dut_ideal = X2**Y2**X2\n", "dut_ideal.name = 'ideal'\n", "\n", "# Extrapolate to DC with different methods\n", "dut_dc_rational = dut.extrapolate_to_dc(kind='rational', dc_sparam=[[0,1],[1,0]])\n", "dut_dc_rational.name = 'rational'\n", "dut_dc_linear = dut.extrapolate_to_dc(kind='linear', dc_sparam=[[0,1],[1,0]])\n", "dut_dc_linear.name = 'linear'\n", "dut_dc_cubic = dut.extrapolate_to_dc(kind='cubic', dc_sparam=[[0,1],[1,0]])\n", "dut_dc_cubic.name = 'cubic'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "plt.title('Step Response')\n", "dut_ideal.plot_z_time_step(0, 0)\n", "dut_dc_rational.plot_z_time_step(0, 0)\n", "dut_dc_cubic.plot_z_time_step(0, 0)\n", "dut_dc_linear.plot_z_time_step(0, 0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dut_ideal.s11['0-2ghz'].plot_s_smith()\n", "dut_dc_rational.s11['0-2ghz'].plot_s_smith()\n", "dut_dc_cubic.s11['0-2ghz'].plot_s_smith()\n", "dut_dc_linear.s11['0-2ghz'].plot_s_smith()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interpolation basis" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default S-parameters are interpolated, but it's possible to interpolate also other parameters such as T, ABCD, Z or Y-parameters.\n", "\n", "Usually S-parameters are the best choice, but in this case T-parameters give better results. Note that T-parameters are defined only for two-ports with non-zero S21. It probably isn't the best choice in most cases but for well matched transmissive two-ports it might be worth trying." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dut_dc_cubic_t = dut.extrapolate_to_dc(kind='cubic', dc_sparam=[[0,1],[1,0]], basis='t')\n", "dut_dc_cubic_t.name = 'cubic T'\n", "dut_dc_cubic.name = 'cubic S'\n", "\n", "plt.figure()\n", "plt.title('Step Response')\n", "dut_ideal.plot_z_time_step(0, 0)\n", "dut_dc_cubic.plot_z_time_step(0, 0)\n", "dut_dc_cubic_t.plot_z_time_step(0, 0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dut_ideal.s11['0-2ghz'].plot_s_smith()\n", "dut_dc_cubic.s11['0-2ghz'].plot_s_smith()\n", "dut_dc_cubic_t.s11['0-2ghz'].plot_s_smith()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.16" }, "toc": { "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "toc_cell": false, "toc_position": {}, "toc_section_display": "block", "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 4 }